package com.wnxy.sddfp.trade.service.impl;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.system.UserInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wnxy.sddfp.client.bank.TradeLogApi;
import com.wnxy.sddfp.common.exception.Assert;
import com.wnxy.sddfp.common.model.BaseResult;
import com.wnxy.sddfp.common.model.dto.query.BorrowRecordQuery;
import com.wnxy.sddfp.common.model.dto.trade.BorrowRecordDTO;
import com.wnxy.sddfp.common.model.vo.UserInfoVo;
import com.wnxy.sddfp.common.model.vo.borrow.BorrowRecordVo;
import com.wnxy.sddfp.common.model.vo.borrow.BorrowSyncRecordVo;
import com.wnxy.sddfp.common.result.Result;
import com.wnxy.sddfp.common.result.enums.impl.ResultCode;
import com.wnxy.sddfp.common.utils.Pages;
import com.wnxy.sddfp.common.utils.TokenUtils;
import com.wnxy.sddfp.system.api.UserApi;
import com.wnxy.sddfp.trade.entity.BorrowRecord;
import com.wnxy.sddfp.trade.mapper.BorrowRecordMapper;
import com.wnxy.sddfp.trade.service.IBorrowRecordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author yellow Docter
 * @date 2023 -07-31
 * @desc    Primary可以理解为默认优先选择, 同时不可以同时设置多个,
 *          内部实质是设置BeanDefinition的primary属性
 */
@Slf4j
@Service
public class IBorrowRecordServiceImpl extends ServiceImpl<BorrowRecordMapper, BorrowRecord> implements IBorrowRecordService {


    @Autowired
    private UserApi userApi;

    @Autowired
    private TradeLogApi tradeLogApi;

    @Override
    public void addBorrowRecord(BorrowRecordDTO borrowRecordDTO) {

        //01 拿到 用户信息
        String userId = TokenUtils.getTokenUserId();
        //通过用户ID 查询用户信息
        //从 trade-服务中、远程调用 system 拿到用户信息
        UserInfoVo userInfoVo = userApi.findUserById(userId);
        System.out.println("userInfoVo = " + userInfoVo);
        //02 创建 borrow 记录 存储到db中

        BorrowRecord borrowRecord = new BorrowRecord();

        //用户标记 userId
        borrowRecord.setUserId(Long.valueOf(userId));
        //用户编码
        borrowRecord.setUserCode(userInfoVo.getUserCode());

        borrowRecord.setBorrowRecordNo("BO_" + UUID.randomUUID().toString().substring(0,10));

        borrowRecord.setDescription("借款旅游");
        borrowRecord.setType("借款");

        //借款天数
        borrowRecord.setPeriod(borrowRecordDTO.getPeriod());

        //投资年化利率
        borrowRecord.setInvestRate(new BigDecimal("0.13"));
        //借款年化利率
        borrowRecord.setBorrowerRate(new BigDecimal("0.13"));
        //平台佣金年化利率
        borrowRecord.setCommissionRate(new BigDecimal("0.12"));

        // 还款方式
        borrowRecord.setRepaymentWay("DEBX");
        // 借款金额
        borrowRecord.setAmount(new BigDecimal(borrowRecordDTO.getAmount()));
        //借款状态
        borrowRecord.setBorrowStatus("NEW");
        //创建时间
        borrowRecord.setCreateDate(new Date());
        //确认时间
        borrowRecord.setModifyDate(new Date());
        // 数据是否同步 默认
        borrowRecord.setStatus(false);
        //流水号不给、借款有审核 审核的时候 给流水号
//        borrowRecord.setReqCode("");

        String name = queryConut(userInfoVo);
        log.info("borrow借款表述name===>{}",name);
        borrowRecord.setName(name);

        //share-jdbc  会自动进行分库分表
        this.save(borrowRecord);
        log.info("保存借款记录成功：{}",borrowRecord);
    }

    @Override
    public Pages<BorrowRecordVo> queryBorrowRecord(Integer pageNum, Integer pageSize, BorrowRecordQuery borrowRecordQuery) {

        //1. 创建分页对象
        IPage<BorrowRecord> pageParams = new Page<>(pageNum,pageSize);

        //2. 创建条件对象
        LambdaQueryWrapper<BorrowRecord> queryWrapper = Wrappers.lambdaQuery(BorrowRecord.class);
        // 借款期限 -- 区间
        if (borrowRecordQuery.getStartPeriod() != null) {
            queryWrapper.ge(BorrowRecord::getPeriod, borrowRecordQuery.getStartPeriod());
        }
        if (borrowRecordQuery.getEndPeriod() != null) {
            queryWrapper.le(BorrowRecord::getPeriod, borrowRecordQuery.getEndPeriod());
        }

        // 借款状态
        if (StringUtils.isNotBlank(borrowRecordQuery.getBorrowStatus())) {
            queryWrapper.eq(BorrowRecord::getBorrowStatus, borrowRecordQuery.getBorrowStatus());
        }
        // 名称
        if (StringUtils.isNotBlank(borrowRecordQuery.getName())) {
            queryWrapper.like(BorrowRecord::getName, borrowRecordQuery.getName());
        }

        //3. 分页条件查询
        IPage<BorrowRecord> pageData = this.page(pageParams, queryWrapper);

        //3.1 获取当前页数据
        List<BorrowRecord> borrowRecordList = pageData.getRecords();
        //3.2 目标是把：List<BorrowRecord>  --->  List<BorrowRecordVo>
        // 通过hutool的工具类copyToList()方法：参数1：数据源集合； 参数2：要转换的对象类型
        List<BorrowRecordVo> voList = BeanUtil.copyToList(borrowRecordList, BorrowRecordVo.class);

        // List<BorrowRecord>  ===> List<BorrowRecordVo>
        //stream
//        List<BorrowRecordVo> recordVos = borrowRecordList.stream().map(borrowRecord -> {
//            BorrowRecordVo borrowRecordVo = new BorrowRecordVo();
//            return borrowRecordVo;
//        }).collect(Collectors.toList());

        //4. 返回结果
        Pages<BorrowRecordVo> pages = new Pages<>();
        pages.setList(voList);
        pages.setPageNum(pageNum);
        pages.setPageSize(pageSize);
        pages.setTotal(pageData.getTotal());
        return pages;
    }

    @Override
    public String verifyStatus(String approveStatus, String borrowRecordId) {

        //01 拿到 借款记录
        BorrowRecord borrowRecord = getById(Long.valueOf(borrowRecordId));

        //更新流水号 REQ_CODE 、更新 确认时间
        String REQ_CODE = "REQ_" + UUID.randomUUID().toString().substring(0,10);
        update(
                Wrappers.lambdaUpdate(BorrowRecord.class)
                        .set(BorrowRecord::getReqCode,REQ_CODE)
                        .set(BorrowRecord::getModifyDate,new Date())
                        .eq(BorrowRecord::getId,Long.valueOf(borrowRecordId))
        );

        //组装BorrowSyncRecordVo
        //BeanUtil.copyProperties  hutool 工具进行属性复制
        BorrowSyncRecordVo borrowSyncRecordVo = BeanUtil.copyProperties(borrowRecord, BorrowSyncRecordVo.class);

        //02 远程调用
        // BorrowSyncRecordVo  把 vo 发送到 bank-access 系统中
        //XXX  xxx = tradeApi.borrowSyncStatus(borrowSyncRecordVo);
        Result<BaseResult> result = tradeLogApi.syncBorrowRecord(borrowSyncRecordVo);
        BaseResult baseResult = result.getData();
        if (StringUtils.isNotBlank(baseResult.getRespMsg())){
            if (baseResult.getRespMsg().equals("成功")){
                //成功后 进行 approveStatus 状态改变
                update(
                        Wrappers.lambdaUpdate(BorrowRecord.class)
                                .set(BorrowRecord::getBorrowStatus,"审核通过")
                                .set(BorrowRecord::getStatus,approveStatus)
                                .set(BorrowRecord::getModifyDate,new Date())
                                .eq(BorrowRecord::getId,Long.valueOf(borrowRecordId))
                );
                return "借款审核通过...";
            }
        }
        return result.getData().toString();
    }

    /**
     * 需要描述、用户的第几次借款
     * @param userInfoVo
     * @return
     */
    private String queryConut(UserInfoVo userInfoVo) {

        //String name = "张";   张三丰
        String name = userInfoVo.getUserName().substring(0, 1);

        //判断性别
        String sex = getGender(userInfoVo.getIdentityCode());

        //通过 UserCode 查询 第几次借款
        //不要使用 userId
        Long count = count(Wrappers.lambdaQuery(BorrowRecord.class)
                .eq(BorrowRecord::getUserCode,userInfoVo.getUserCode()));

        int num = 0;
        if (count == null){
            num = 1;
        }else{
            num = Integer.parseInt(count.toString()) + 1;
        }
        return name + sex+" 第" + num  +"次借款";
    }

    /**
     * 根据身份证号码返回性别：先生、女士
     */
    private String getGender(String identityCode) {
        // 判断身份证号码必须是18位
        Assert.error(
                identityCode==null || identityCode.length()!=18,
                ResultCode.DATA_IS_WRONG);
        // 截取
        Integer n = Integer.parseInt(identityCode.substring(16,17));
        return n % 2 == 0 ? "女士" : "先生";
    }
}
